package com.ftg.learn.util;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ftg.learn.dto.DimDto;
import com.mysql.cj.util.StringUtils;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Objects;

/**
 * 不太好，暂时采用 侵入式设计 ，侵入度较高
 *
 * @author kangjx
 * @createTime 2022/10/27
 */
@SuppressWarnings("all")
@Component
public abstract class AbstractController<T extends ServiceImpl, E> {

    public IService<E> iService;

    public void setIservice(){

        ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
        Type[] ts = ptClass.getActualTypeArguments();
        System.out.println(Arrays.toString(ts)+"你看我像谁");

        if(Objects.isNull(ts) || ts[0] == null){
            throw new RuntimeException("请正确传递controller泛型");
        }
        String servicePath = ts[0].getTypeName();
        System.out.println(servicePath+"就是serviceImpl的一个子类的全路径");
        try {
            Class serviceClass = Class.forName(servicePath);

            this.iService = (IService<E>) SpringApplicationContext.getBean(serviceClass);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("传递的泛型不能正常反射，请查看泛型");
        }
    }

    public IService<E> getIService(){
        this.setIservice();
        return this.iService;
    }

    /**
     * 通用的添加方法
     *
     * @param e 实体
     * @return ResultJson
     */
    @PostMapping("/saveT")
    @ApiOperation("通用实体添加方法")
    public ResultJson saveT(@RequestBody @ApiParam(value = "添加的实体") E e) {
        return ResultJson.OK(this.getIService().save(e));
    }

    /**
     * 通用的添加方法
     *
     * @param e 实体
     * @return ResultJson
     */
    @PutMapping("/modifyT")
    @ApiOperation("通用实体修改方法,按照主键")
    public ResultJson modifyT(@RequestBody @ApiParam(value = "修改实体") E e) {
        return ResultJson.OK(this.getIService().updateById(e));
    }


    /**
     * 通用的删除方法
     *
     * @param id 实体
     * @return ResultJson
     */
    @DeleteMapping("/deleteT")
    @ApiOperation("通用的删除方法,按照主键")
    public ResultJson deleteT(@RequestParam("id") @ApiParam(value = "主键", required = true) Serializable id) {
        return ResultJson.OK(this.getIService().removeById(id));
    }

    /**
     * 通用的查询方法
     *
     * @param id 主键
     * @return ResultJson
     */
    @ApiOperation("通用主键查一实体操作")
    @PutMapping("/findone/{id}")
    public ResultJson findOne(@PathVariable("id") @ApiParam(value = "主键") Serializable id) {
        return ResultJson.OK(this.getIService().getById(id));
    }


    /**
     * 通用查看全部信息
     *
     * @return ResultJson
     */
    @GetMapping("/list")
    @ApiOperation("通用查看全部信息")
    public ResultJson list() {
        return ResultJson.OK(this.getIService().list());
    }

    /**
     * 通用的带参查看全部
     *
     * @param cols 大量列名
     * @param para 大量列名的参数
     * @return ResultJson
     */
    @PostMapping("/listWithParam")
    @ApiOperation("通用的带参查看全部")
    @SuppressWarnings("all")
    public ResultJson listWithParam(@RequestBody(required = false) @ApiParam(value = "模糊查询参数封装") DimDto dimDto) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dimDto)) {
            for (int i = 0; i < dimDto.getCols().size(); i++) {
                if (!StringUtils.isNullOrEmpty(dimDto.getPara().get(i))) {
                    queryWrapper.like(dimDto.getCols().get(i), dimDto.getPara().get(i));
                }
            }
        }
        return ResultJson.OK(this.getIService().list(queryWrapper));
    }

    /**
     * 通用带模糊分页功能
     *
     * @param cols 大量列名
     * @param para 大量列名的参数
     * @return ResultJson
     */
    @PostMapping("/pageWithParam")
    @ApiOperation("通用带模糊分页功能")
    @SuppressWarnings("all")
    public ResultJson pageWithParam(
            @RequestParam("page") @ApiParam(value = "页码", defaultValue = "1") int page,
            @RequestParam("limit") @ApiParam(value = "显示条目", defaultValue = "10") int limit,
            @RequestBody(required = false) @ApiParam(value = "模糊查询参数封装") DimDto dimDto) {
        IPage<E> iPage = new Page<>(page, limit);
        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dimDto)) {
            for (int i = 0; i < dimDto.getCols().size(); i++) {
                if (!StringUtils.isNullOrEmpty(dimDto.getPara().get(i))) {
                    queryWrapper.like(dimDto.getCols().get(i), dimDto.getPara().get(i));
                }
            }
        }
        return ResultJson.OK(this.getIService().page(iPage, queryWrapper));
    }

}
